//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Xml;
using System.Reflection;
using System.IO;
using ConfigurationWizard.Controls;
using ConfigurationWizard.Validation;
using System.Collections.ObjectModel;
using ConfigurationWizard.Configuration;
using System.Configuration;


namespace ConfigurationWizard
{
    public partial class Checker : UserControl
    {
        private BackgroundWorker worker;
        private bool DependencyCheckingSuccess = true;
        private Collection<DependencyBase> dependencies = null;

        public Checker()
        {
            InitializeComponent();
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            worker.DoWork += new DoWorkEventHandler(ProcessDependencyChecking);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ProcessDependencyCheckingCompleted);
            worker.ProgressChanged += new ProgressChangedEventHandler(ProcessDependencyCheckingProgressUpdated);
            LoadDependencies();
        }

        private void LoadDependencies()
        {
            DependencySection section = (DependencySection)ConfigurationManager.GetSection("dependencyChecker");
            DependencyConfigurationReader reader = new DependencyConfigurationReader(section);
            this.dependencies = reader.AnalyzeDependencies();

            foreach (DependencyBase dependency in this.dependencies)
            {
                DependencyViewControl control = new DependencyViewControl(dependency.Title, dependency.Explanation,
                                                                          dependency.DownloadUrl, dependency.ScriptName);

                control.Top = CalculateControlTop(this.dependenciesPanel);
                this.dependenciesPanel.Controls.Add(control);
            }
        }

        private void OnWizardCancelled(object sender, EventArgs e)
        {
            worker.CancelAsync();
        }

        private void Checker_Load(object sender, EventArgs e)
        {
            ((Shell)this.Parent.Parent).WizardCanceled += new EventHandler<EventArgs>(OnWizardCancelled);
            ScanDependencies();
        }

        private void ScanDependencies()
        {
            this.progressLabel.Text = "Scanning for dependencies";
            this.rescanButton.Enabled = false;
            ((Shell)this.Parent.Parent).nextButton.Enabled = false;
            this.checkerProgressBar.Value = 0;
            worker.RunWorkerAsync();
        }

        private void ProcessDependencyCheckingProgressUpdated(object sender, ProgressChangedEventArgs e)
        {
            DependencyCheckingProgress state = (DependencyCheckingProgress)e.UserState;
            if (state.CurrentDependencyIndex != this.dependenciesPanel.Controls.Count - 1)
            {
                this.checkerProgressBar.Value += e.ProgressPercentage;
            }
            else
            {
                this.checkerProgressBar.Value = 100;
            }
            this.DependencyCheckingSuccess &= (state.Success || state.Optional);

            DependencyViewControl view = (DependencyViewControl)this.dependenciesPanel.Controls[state.CurrentDependencyIndex];

            if (state.Success)
            {
                view.SetSuccessMode();
            }
            else
            {
                if (state.Optional)
                {
                    view.SetWarningMode();
                }
                else 
                {
                    view.SetErrorMode();
                }
            }
            view.Top = CalculateControlTop(this.dependenciesPanel, state.CurrentDependencyIndex);
            
            for (int i = state.CurrentDependencyIndex; i < this.dependenciesPanel.Controls.Count; i++)
            {
                DependencyViewControl control = (DependencyViewControl)this.dependenciesPanel.Controls[i];
                control.Top = CalculateControlTop(this.dependenciesPanel, i);
            }
        }
    
        private void ProcessDependencyCheckingCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.rescanButton.Enabled = true;
            this.progressLabel.Text = "Scan completed";

            if (this.Parent != null && this.DependencyCheckingSuccess)
            {
                ((Shell)this.Parent.Parent).nextButton.Enabled = true;
                ((Shell)this.Parent.Parent).nextButton.Focus();
            }
        }

        private void ProcessDependencyChecking(object sender, DoWorkEventArgs e)
        {
            int increment = 100 / dependencies.Count;
            for (int i = 0; i < dependencies.Count; i++)
			{
                if (worker.CancellationPending)
                    return;

                DependencyBase dependency =  dependencies[i];
                bool success = dependency.Evaluate();                
                DependencyCheckingProgress progress = new DependencyCheckingProgress(i, 
                                                                                    success, 
                                                                                    dependency.Optional);
                worker.ReportProgress(increment, progress);
			}
        }

        private void rescanButton_Click(object sender, EventArgs e)
        {
            ScanDependencies();
        }

        private static int CalculateControlTop(Panel container, int upTo)
        {
            int resultHeight = 0;
            for (int i = 0; i < upTo; i++)
            {
                resultHeight += container.Controls[i].Height;
            }

            return resultHeight;
        }

        private static int CalculateControlTop(Panel container)
        {
            return CalculateControlTop(container, container.Controls.Count);   
        }
    }

    class DependencyCheckingProgress
    {
        private bool success;
        private bool optional;
        private int currentDependencyIndex;

        public DependencyCheckingProgress(int currentDependencyIndex, bool success, bool optional)
        {
            this.success = success;
            this.currentDependencyIndex = currentDependencyIndex;
            this.optional = optional;
        }

        public bool Success
        {
            get
            {
                return success;
            }
        }

        public bool Optional
        {
            get
            {
                return optional;
            }
        }

        public int CurrentDependencyIndex
        {
            get
            {
                return currentDependencyIndex;
            }
        }
    }
}
